package com.zhoug.zmui.gusturelock;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;


import com.zhoug.common.utils.LogUtils;
import com.zhoug.zmui.R;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

/**
 * zmui_style_GestureLockViewGroup
 * 手指密码控件
 * @Author 35574
 * @Date 2020/10/30
 * @Description
 */
public class ZMUIGestureLockViewGroup extends RelativeLayout {
    private static final String TAG = ">>>GestureLockViewGroup";
    private static final boolean DEBUG = false;

    /***保存所有的GestureLockView*/
    private ZMUIGestureLockView[] mGestureLockViews;
    private Paint mPaint;
    private Path mPath = new Path();//手势绘制点的连线
    /***选中的id*/
    private List<Integer> mChooser = new ArrayList<>();

    /***几行*/
    private int mRowCount = 3;
    /***几列*/
    private int mColumnCount = 3;
    /***间隔距离和GestureLockView宽度比率*/
    private float mIntervalRate = 0.4f;
    /*** 内圆半径占比*/
    private float mInnerRadiusRate = 0.3f;
    /*** 画笔的宽度*/
    private int mStrokeWidth = 3;
    /***点击前内圆颜色*/
    private int mColorNoFingerInner = Color.parseColor("#808080");
    /***点击前外圆颜色*/
    private int mColorNoFingerOuter = Color.parseColor("#A7A7F1");
    /****点中时内圆和外圆颜色*/
    private int mColorFingerOn = Color.parseColor("#2222DD");
    /***手指抬起后内圆和外圆颜色*/
    private int mColorFingerUp = Color.RED;
    /***是否画手势轨迹*/
    private boolean drawPath = true;
    /***是否绘制内圆*/
    private boolean drawInnerCircle = true;//
    /***最少连接点数*/
    private int mMinLength = 3;

    // 指引线:最后一个点和手指位置的连线

    /**
     * 解锁模式
     */
    public static final int MODE_ANSWER = 1;
    /**
     * 录入密码模式
     */
    public static final int MODE_INPUT = 2;
    /**
     * 模式
     */
    private int mMode = MODE_ANSWER;

    /***解锁模式下的答案*/
    private List<Integer> mAnswer = Arrays.asList(1, 2, 3, 4, 5, 6);
    /***录入模式下第一次录入的值*/
    private List<Integer> mInputValues;

    /**
     * 监听器
     */
    private OnGestureLockViewListener mOnGestureLockViewListener;


    public ZMUIGestureLockViewGroup(Context context) {
        this(context, null);
    }

    public ZMUIGestureLockViewGroup(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.zmui_style_GestureLockViewGroup);
    }

    public ZMUIGestureLockViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ZMUIGestureLockViewGroup, defStyleAttr, R.style.zmui_style_GestureLockViewGroup);
        int indexCount = a.getIndexCount();
        for(int i=0;i<indexCount;i++){
            int attr = a.getIndex(i);
            if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_rowCount) {
                mRowCount = a.getInt(attr, 3);
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_columnCount) {
                mColumnCount = a.getInt(attr, 3);
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_intervalRate) {
                mIntervalRate = a.getFloat(attr, 0.4f);
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_innerRadiusRate) {
                mInnerRadiusRate = a.getFloat(attr, 0.3f);
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_strokeWidth) {
                mStrokeWidth = a.getDimensionPixelOffset(attr, 3);
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_colorNoFingerInner) {
                mColorNoFingerInner = a.getColor(attr, Color.parseColor("#808080"));
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_colorNoFingerOuter) {
                mColorNoFingerOuter = a.getColor(attr, Color.parseColor("#A7A7F1"));
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_colorFingerOn) {
                mColorFingerOn = a.getColor(attr, Color.parseColor("#2222DD"));
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_colorFingerUp) {
                mColorFingerUp = a.getColor(attr, Color.parseColor("#ff0000"));
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_drawPath) {
                drawPath = a.getBoolean(attr, true);
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_drawInnerCircle) {
                drawInnerCircle = a.getBoolean(attr, true);
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_minLength) {
                mMinLength = a.getInt(attr, 3);
            } else if (attr == R.styleable.ZMUIGestureLockViewGroup_zmui_gestureLock_mode) {
                mMode = a.getInt(attr, MODE_ANSWER);
            }

        }
        a.recycle();
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mStrokeWidth);
        mPaint.setColor(mColorFingerOn);

    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        addGestureLockViews();
    }

    private void addGestureLockViews() {
        if (DEBUG) {
            LogUtils.d(TAG, "addGestureLockViews:mRowCount=" + mRowCount + ",mColumnCount=" + mColumnCount);
        }
        removeAllViews();
        ZMUIGestureLockView lockView;
        mGestureLockViews = new ZMUIGestureLockView[mRowCount * mColumnCount];
        for (int i = 0; i < mGestureLockViews.length; i++) {
            lockView = new ZMUIGestureLockView(getContext());
            mGestureLockViews[i] = lockView;
            setGestureLockViewStyle(lockView);
            lockView.setId(i + 1);
            LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            //第一个
            if (i == 0) {
                layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
                layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
            }
            if (i % mColumnCount != 0) {
                // 不是每行的第一个，则设置位置为前一个的右边
                layoutParams.addRule(RelativeLayout.RIGHT_OF, mGestureLockViews[i - 1].getId());
            }
            //从第二行开始，设置为上一行同一位置View的下面
            if (i >= mColumnCount) {
                layoutParams.addRule(RelativeLayout.BELOW, mGestureLockViews[i - mColumnCount].getId());
            }
            addView(lockView, layoutParams);
        }
    }

    /**
     * 设置GestureLockView的样式
     *
     * @param lockView
     */
    private void setGestureLockViewStyle(ZMUIGestureLockView lockView) {
        if (lockView != null) {
            lockView.setColorFingerOn(mColorFingerOn);
            lockView.setColorFingerUp(mColorFingerUp);
            lockView.setColorNoFingerInner(mColorNoFingerInner);
            lockView.setColorNoFingerOuter(mColorNoFingerOuter);
            lockView.setInnerRadiusRate(mInnerRadiusRate);
            lockView.setStrokeWidth(mStrokeWidth);
            lockView.setDrawInnerCircle(drawInnerCircle);
        }
    }

    private void updateStyle() {
        if (mGestureLockViews != null && mGestureLockViews.length > 0) {
            for (int i = 0; i < mGestureLockViews.length; i++) {
                setGestureLockViewStyle(mGestureLockViews[i]);
            }
        }
        if (DEBUG) {
            LogUtils.d(TAG, "updateStyle:");
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (DEBUG) {
            LogUtils.d(TAG, "onSizeChanged:");
        }
        updateStyle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (DEBUG) {
            LogUtils.d(TAG, "onMeasure:"+ String.format(Locale.CANADA,"widthSize=%d,heightSize=%d",widthSize,heightSize));
        }
        if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
            setGestureLockViewLayout(widthSize,heightSize);
        } else if (widthMode == MeasureSpec.EXACTLY) {
            //宽度确定
            int width=widthSize;
            int height=0;
            if(heightSize>0){
                height= Math.min(width-getPaddingStart()-getPaddingEnd()+getPaddingTop()+getPaddingBottom(),heightSize);
            }else{
                height=widthSize;
            }
            setGestureLockViewLayout(width,height);
            setMeasuredDimension(width, height);
        } else if (heightMode == MeasureSpec.EXACTLY) {
            //高度确定 ok
            int width=0;
            int height=heightSize;
            if(widthSize>0){
                width= Math.min(height-getPaddingTop()-getPaddingBottom()+getPaddingStart()+getPaddingEnd(),widthSize);
            }else{
                width=heightSize;
            }
            setGestureLockViewLayout(width,height);
            setMeasuredDimension(width, height);
        } else {
            //宽高不确定 wrap_content
            //使用GestureLockView默认宽高
            View childAt = getChildAt(0);
            childAt.measure(widthMeasureSpec, heightMeasureSpec);
            //child默认宽高
            int childWidth = childAt.getMeasuredWidth();
            int childHeight = childAt.getMeasuredWidth();
            //根据Child默认宽高计算出的容器宽高
            int width= (int) (childWidth*(mColumnCount + (mColumnCount + 1) * mIntervalRate))+getPaddingStart()+getPaddingEnd();
            int height=(int)(childHeight*(mRowCount + (mRowCount + 1) * mIntervalRate))+getPaddingTop()+getPaddingBottom();
            if(widthSize>0){
                width= Math.min(width,widthSize);
            }
            if(heightSize>0){
                height= Math.min(height,heightSize);
            }
            setGestureLockViewLayout(width,height);
            setMeasuredDimension(width, height);
        }
    }

    /**
     * 设置GestureLockView的宽高
     * @param width
     * @param height
     */
    private void setGestureLockViewLayout(int width,int height){
        if (DEBUG) {
            LogUtils.d(TAG, "setGestureLockViewLayout:width="+width+",height="+height);
        }
        //宽高确定
        //宽度平分成多少份
        float n = mColumnCount + (mColumnCount + 1) * mIntervalRate;
        float w = (width - getPaddingStart() - getPaddingEnd()) / n;
        //高度平分成多少份
        n = mRowCount + (mRowCount + 1) * mIntervalRate;
        float h = (height - getPaddingTop() - getPaddingBottom()) / n;
        int lockViewSize = (int) Math.min(w, h);
        int interval = (int) (lockViewSize * mIntervalRate);
        //垂直方向上剩余的一半设置为第一行的topMargin;
        int topMargin = (height - getPaddingTop() - getPaddingBottom() - (mRowCount * lockViewSize + (mRowCount - 1) * interval)) >> 1;
        //水平方向上剩余的一半设置为第一列的leftMargin;
        int leftMargin = (width - getPaddingStart() - getPaddingEnd() - (mColumnCount * lockViewSize + (mColumnCount - 1) * interval)) >> 1;
        if (DEBUG) {
            LogUtils.d(TAG, "onMeasure:lockViewSize=" + lockViewSize);
        }
        ZMUIGestureLockView lockView;
        for (int i = 0; i < mGestureLockViews.length; i++) {
            lockView = mGestureLockViews[i];
            LayoutParams layoutParams = (LayoutParams) lockView.getLayoutParams();
            layoutParams.width = lockViewSize;
            layoutParams.height = lockViewSize;
            layoutParams.rightMargin = interval;
            layoutParams.bottomMargin = interval;
            if (i < mColumnCount) {
                //第一行
                layoutParams.topMargin = topMargin;
            }
            if (i % mColumnCount == 0) {
                //第一列
                layoutParams.leftMargin = leftMargin;
            }
            lockView.setLayoutParams(layoutParams);
        }
    }


    /**
     * 打印事件类型
     *
     * @param event
     */
    private void printAction(MotionEvent event) {
        if (DEBUG) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    LogUtils.d(TAG, "pointAction:ACTION_DOWN");
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    LogUtils.d(TAG, "pointAction:ACTION_POINTER_DOWN");

                    break;
                case MotionEvent.ACTION_MOVE:
                    LogUtils.d(TAG, "pointAction:ACTION_MOVE");
                    break;
                case MotionEvent.ACTION_UP:
                    LogUtils.d(TAG, "pointAction:ACTION_UP");
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    LogUtils.d(TAG, "pointAction:ACTION_POINTER_UP");

                    break;
                case MotionEvent.ACTION_CANCEL:
                    LogUtils.d(TAG, "pointAction:ACTION_CANCEL");
                    break;
            }
        }
    }


    private PointF lastPoint = new PointF();//最后连接的点
    private PointF endPoint = new PointF();//手指的位置

    @Override
    public boolean onTouchEvent(MotionEvent event) {
//        printAction(event);
        if (!isEnabled()) {
            return false;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                _reset();
                endPoint.x = event.getX();
                endPoint.y = event.getY();
                break;

            case MotionEvent.ACTION_MOVE:
                ZMUIGestureLockView touchLockView = getTouchLockView(event);
                if (touchLockView != null) {
                    //添加选中
                    if (!mChooser.contains(touchLockView.getId())) {
                        mChooser.add(touchLockView.getId());
                        if (drawPath) {
                            //修改状态
                            touchLockView.setStatus(ZMUIGestureLockView.Status.FINGER_ON);
                        }
                        lastPoint.x = (touchLockView.getLeft() + touchLockView.getRight()) >> 1;
                        lastPoint.y = (touchLockView.getTop() + touchLockView.getBottom()) >> 1;
                        if (mChooser.size() == 1) {
                            //第一个
                            mPath.moveTo(lastPoint.x, lastPoint.y);
                        } else {
                            mPath.lineTo(lastPoint.x, lastPoint.y);
                        }
                    }
                }
                endPoint.x = event.getX();
                endPoint.y = event.getY();
                break;
            case MotionEvent.ACTION_UP:
                //取消指引线
                endPoint.x = lastPoint.x;
                endPoint.y = lastPoint.y;
                //解密模式
                if (mMode == MODE_ANSWER) {
                    boolean b = check(mAnswer);
                    if (!b) {
                        changeChooseStatus();
                        mPaint.setColor(mColorFingerUp);
                        resetDelayed();
                    }
                    if (mOnGestureLockViewListener != null) {
                        mOnGestureLockViewListener.onMatched(b);
                    }
                } else if (mMode == MODE_INPUT) {
                    //录入模式
                    if (mChooser.size() >= mMinLength) {
                        //第一次录入,保存录入数据
                        if (mInputValues == null) {
                            mInputValues = new ArrayList<>(mChooser);
                            if (mOnGestureLockViewListener != null) {
                                mOnGestureLockViewListener.onInputSuccess(mInputValues, true);
                            }
                            resetDelayed();
                        } else {
                            //非第一次录入,验证两次录入是否一致

                            if (check(mInputValues)) {
                                if (mOnGestureLockViewListener != null) {
                                    mOnGestureLockViewListener.onInputSuccess(mInputValues, false);
                                }
                            } else {
                                changeChooseStatus();
                                mPaint.setColor(mColorFingerUp);
                                resetDelayed();
                                if (mOnGestureLockViewListener != null) {
                                    mOnGestureLockViewListener.onInputError(OnGestureLockViewListener.ERROR_INPUT_UN_MATCH, "两次录入不一样");
                                }
                            }

                        }
                    } else {
                        //连接点数未达到最少要求
                        changeChooseStatus();
                        mPaint.setColor(mColorFingerUp);
                        resetDelayed();
                        if (mOnGestureLockViewListener != null) {
                            mOnGestureLockViewListener.onInputError(OnGestureLockViewListener.ERROR_INPUT_MIN_LENGTH, "最少连接" + mMinLength + "个点");
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                _reset();
                break;
        }
        postInvalidate();
        return true;
    }


    /**
     * 获取触摸的GestureLockView
     *
     * @param event
     * @return
     */
    private ZMUIGestureLockView getTouchLockView(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        ZMUIGestureLockView lockView;
        for (int i = 0; i < mGestureLockViews.length; i++) {
            lockView = mGestureLockViews[i];
            if (x >= lockView.getLeft() && x <= lockView.getRight() && y >= lockView.getTop() && y <= lockView.getBottom()) {
                return lockView;
            }
        }
        return null;
    }

    /**
     * 手指抬起时改变选中的GestureLockView的状态
     */
    private void changeChooseStatus() {
        ZMUIGestureLockView lockView;
        for (int i = 0; i < mGestureLockViews.length; i++) {
            lockView = mGestureLockViews[i];
            if (mChooser.contains(lockView.getId())) {
                lockView.setStatus(ZMUIGestureLockView.Status.FINGER_UP);
            }
        }

    }

    /**
     * 重置所有的状态
     */
    public void reset(){
        _reset();
        invalidate();
    }

    /**
     * 重置所有的状态
     */
    private void _reset() {
        for (int i = 0; i < mGestureLockViews.length; i++) {
            mGestureLockViews[i].setStatus(ZMUIGestureLockView.Status.NO_FINGER);
        }
        lastPoint.x = 0;
        lastPoint.y = 0;
        endPoint.x = 0;
        endPoint.y = 0;
        mPath.reset();
        mChooser.clear();
        mPaint.setColor(mColorFingerOn);
        removeCallbacks(delayedReset);
    }

    /**
     * 延后重置
     */
    private void resetDelayed() {
        removeCallbacks(delayedReset);
        postDelayed(delayedReset, 500);
    }

    /**
     * 手指抬起后间隔一端时间重置状态
     */
    private Runnable delayedReset = new Runnable() {
        @Override
        public void run() {
            _reset();
            invalidate();
        }
    };


    /**
     * 检查用户绘制的手势是否正确
     *
     * @return
     */
    private boolean check(List<Integer> answer) {
        if (DEBUG) {
            LogUtils.d(TAG, "onTouchEvent:answer="+answer);
            LogUtils.d(TAG, "onTouchEvent:mChooser="+mChooser);
        }
        if (answer != null && answer.size() > 0) {
            if (mChooser.size() != answer.size()) {
                return false;
            }
            for (int i = 0; i < answer.size(); i++) {
                if (answer.get(i).intValue() != mChooser.get(i).intValue()) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }


    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (drawPath) {
            if (mChooser.size() > 0) {
                //绘制连线
                if (mPath != null) {
                    canvas.drawPath(mPath, mPaint);
                }
                //绘制指引线
                if (lastPoint.x != 0 && lastPoint.y != 0) {
                    canvas.drawLine(lastPoint.x, lastPoint.y, endPoint.x, endPoint.y, mPaint);
                }

            }
        }
    }

    /**
     * 设置个数
     *
     * @param rawCount    几行 默认:3
     * @param columnCount 几列 默认:3
     */
    public void setCount(int rawCount, int columnCount) {
        if(this.mRowCount!=rawCount || this.mColumnCount!=columnCount){
            this.mRowCount = rawCount;
            this.mColumnCount = columnCount;
            addGestureLockViews();
            requestLayout();
        }
    }

    /**
     * 最少连接点数
     * @param minLength
     */
    public void setMinLength(int minLength) {
        this.mMinLength = minLength;
    }

    /**
     * 间隔距离和GestureLockView宽度比率
     *
     * @param intervalRate 默认0.5f
     */
    public void setIntervalRate(float intervalRate) {
        this.mIntervalRate = intervalRate;
    }

    /**
     * 内圆半径占外圆半径的占比
     *
     * @param mInnerRadiusRate 默认:0.3f
     */
    public void setInnerRadiusRate(float mInnerRadiusRate) {
        this.mInnerRadiusRate = mInnerRadiusRate;
    }

    /**
     * 画笔粗细
     *
     * @param strokeWidth
     */
    public void setStrokeWidth(int strokeWidth) {
        this.mStrokeWidth = strokeWidth;
    }

    /**
     * 点击前内圆颜色
     *
     * @param colorNoFingerInner
     */
    public void setColorNoFingerInner(int colorNoFingerInner) {
        this.mColorNoFingerInner = colorNoFingerInner;
    }

    /**
     * 点击前外圆颜色
     *
     * @param colorNoFingerOuter
     */
    public void setColorNoFingerOuter(int colorNoFingerOuter) {
        this.mColorNoFingerOuter = colorNoFingerOuter;
    }

    /**
     * 点中时内圆和外圆颜色
     *
     * @param colorFingerOn
     */
    public void setColorFingerOn(int colorFingerOn) {
        this.mColorFingerOn = colorFingerOn;
    }

    /**
     * 手指抬起后内圆和外圆颜色
     *
     * @param colorFingerUp
     */
    public void setColorFingerUp(int colorFingerUp) {
        this.mColorFingerUp = colorFingerUp;
    }

    public void setDrawInnerCircle(boolean drawInnerCircle) {
        this.drawInnerCircle = drawInnerCircle;
    }

    /**
     * 设置模式
     *
     * @param mode {@link #MODE_ANSWER#MODE_INPUT}
     */
    public void setMode(int mode) {
        this.mMode = mode;
        mInputValues = null;
    }

    /**
     * 是否绘制手势轨迹
     *
     * @param drawPath
     */
    public void setDrawPath(boolean drawPath) {
        this.drawPath = drawPath;
    }

    public void setAnswer(List<Integer> answer) {
        this.mAnswer = answer;
    }

    /**
     * 设置手势监听
     *
     * @param onGestureLockViewListener
     */
    public void setOnGestureLockViewListener(OnGestureLockViewListener onGestureLockViewListener) {
        this.mOnGestureLockViewListener = onGestureLockViewListener;
    }

    /**
     * 手势监听
     */
    public interface OnGestureLockViewListener {
        /***连接线少于设置的最小值*/
        int ERROR_INPUT_MIN_LENGTH = 1001;
        /***2次输入不一致*/
        int ERROR_INPUT_UN_MATCH = 1002;

        /**
         * 解锁模式:是否匹配
         *
         * @param matched
         */
        void onMatched(boolean matched);

        /**
         * 录入模式的值
         *
         * @param inputs  录入的值
         * @param isFirst 是否是第一次录入,可以判断提示用户再次录入
         */
        void onInputSuccess(List<Integer> inputs, boolean isFirst);

        /***
         * 录入模式错误
         * @param code {@link #ERROR_INPUT_MIN_LENGTH,#ERROR_INPUT_MIN_LENGTH}
         * @param error
         */
        void onInputError(int code, String error);


    }
}
